home *** CD-ROM | disk | FTP | other *** search
- /* MTASK V1.0
-
- A minimal multitasking library for DOS. Copyright 1993 I H Ting.
-
- Disclaimer:
- Use the code at your own peril. I don't promise it actually does anything.
- Even if the world ends when you use it, don't hold me responsible.
-
- Comments and suggestions, however, are welcomed. I can be reached at:
-
- Compuserve ID: 100023,3363
- Internet: cm1826@ccub.wlv.ac.uk
-
- */
-
- #include "stdio.h"
- #include "dos.h"
- #include "stdlib.h"
- #include "conio.h"
- #include "mtask.h"
-
- enum TaskStatus {INVALID, CURRENT, READY, WAITING};
-
- typedef struct {
- unsigned bp;
- unsigned di;
- unsigned si;
- unsigned ds;
- unsigned es;
- unsigned dx;
- unsigned cx;
- unsigned bx;
- unsigned ax;
- unsigned ip;
- unsigned cs;
- unsigned flags;
- } RegsOnStack;
-
-
- typedef struct {
- unsigned sp;
- unsigned ss;
- enum TaskStatus status;
- unsigned *semaphore;
- void *pOwnStack;
- } TaskInfo;
-
- TaskInfo taskList[MAX_TASKS];
-
-
- void interrupt TheScheduler(void);
- void interrupt ChangeTask(void);
- void interrupt (*PrevInterrupt)(void);
- void WakeUpTasks(unsigned *semaphore);
- void EndMultiTasking(void);
- void TidyUp(void);
- int IsDeadLock(void);
-
-
-
-
- static unsigned originalSS, originalSP;
- static unsigned IOsemaphore=0;
-
- static int currentTaskID = 0;
- static char bMultiTasking = 1;
-
-
- static void interrupt TheScheduler(void)
- {
- (*PrevInterrupt)();
- taskList[currentTaskID].ss = _SS;
- taskList[currentTaskID].sp = _SP;
-
- if(taskList[currentTaskID].status==CURRENT)
- taskList[currentTaskID].status = READY;
-
- if(IsDeadLock()) bMultiTasking = 0;
-
- if(!bMultiTasking) { /* stop bMultiTasking */
- disable();
- _SS = originalSS;
- _SP = originalSP;
- setvect(8, PrevInterrupt);
- TidyUp();
- enable();
- return;
- }
-
- do{
- currentTaskID++;
- if(currentTaskID==MAX_TASKS) currentTaskID = 0;
- }while(taskList[currentTaskID].status!=READY);
-
- _SS = taskList[currentTaskID].ss;
- _SP = taskList[currentTaskID].sp;
- taskList[currentTaskID].status = CURRENT;
-
- }
-
- static void interrupt ChangeTask(void)
- {
-
- disable();
- taskList[currentTaskID].ss = _SS;
- taskList[currentTaskID].sp = _SP;
- if(taskList[currentTaskID].status==CURRENT)
- taskList[currentTaskID].status = READY;
-
- if(IsDeadLock()) bMultiTasking = 0;
-
- if(!bMultiTasking) {
- disable();
- _SS = originalSS;
- _SP = originalSP;
- setvect(8, PrevInterrupt);
- TidyUp();
- enable();
- return;
- }
-
- /* find new pTaskFunc */
- do{
- currentTaskID++;
- if(currentTaskID==MAX_TASKS) currentTaskID = 0;
- }while(taskList[currentTaskID].status!=READY);
-
- _SS = taskList[currentTaskID].ss;
- _SP = taskList[currentTaskID].sp;
- taskList[currentTaskID].status = CURRENT;
- enable();
- }
-
-
- static int IsDeadLock(void)
- {
- register int i;
-
- for(i=0; i<MAX_TASKS; i++)
- if(taskList[i].status==READY) return 0;
- return 1;
- }
-
-
- static void TidyUp(void)
- {
- int i;
-
- for(i=0; i<MAX_TASKS; i++) {
- if(taskList[i].pOwnStack) {
- free(taskList[i].pOwnStack);
- taskList[i].pOwnStack = NULL;
- }
- }
- }
-
-
- int AddNewTask(PTaskFunc pTaskFunc)
- {
- RegsOnStack *pRegs;
- unsigned taskID, i;
- void *pNewStack;
-
-
- disable();
- taskID = MAX_TASKS;
- for(i=0; i<MAX_TASKS; i++)
- if (taskList[i].status == INVALID){
- taskID = i;
- break;
- }
- if (taskID == MAX_TASKS){ /* Failed */
- enable();
- return taskID;
- }
-
- pNewStack = malloc(TASK_STACK_SIZE + sizeof(RegsOnStack));
- if (pNewStack==NULL) return MAX_TASKS;
- taskList[taskID].pOwnStack = pNewStack;
- pRegs = (RegsOnStack *) taskList[taskID].pOwnStack +
- TASK_STACK_SIZE - sizeof(RegsOnStack);
-
- taskList[taskID].sp = FP_OFF((RegsOnStack far *) pRegs);
- taskList[taskID].ss = FP_SEG((RegsOnStack far *) pRegs);
-
- pRegs->cs = FP_SEG(pTaskFunc);
- pRegs->ip = FP_OFF(pTaskFunc);
- pRegs->ds = _DS;
- pRegs->es = _DS;
- pRegs->flags = 0x200;
-
- taskList[taskID].status = READY;
- enable();
- return taskID;
- }
-
-
- void interrupt StartMultiTasking(void)
- {
- disable();
-
- PrevInterrupt = getvect(8);
- setvect(8, TheScheduler);
-
- originalSS = _SS;
- originalSP = _SP;
-
- _SS = taskList[currentTaskID].ss;
- _SP = taskList[currentTaskID].sp;
- enable();
- }
-
-
- void RemoveTask(unsigned taskID)
- {
- disable();
- if(taskID <MAX_TASKS){
- taskList[taskID].status = INVALID;
- if(taskList[taskID].pOwnStack)
- free(taskList[taskID].pOwnStack);
- taskList[taskID].pOwnStack = NULL;
- }
- enable();
- ChangeTask();
- }
-
-
- void InitMultiTasking(void)
- {
- int i;
-
- for(i=0; i<MAX_TASKS; i++) {
- taskList[i].status = INVALID;
- taskList[i].semaphore = NULL;
- taskList[i].pOwnStack = NULL;
- }
- }
-
-
- void EndMultiTasking(void)
- {
- bMultiTasking = 0;
- ChangeTask();
- }
-
-
-
-
- void MTWait(unsigned *semaphore)
- {
- disable();
- while(*semaphore) {
- taskList[currentTaskID].status = WAITING;
- taskList[currentTaskID].semaphore = semaphore;
- ChangeTask();
- disable();
- }
- *semaphore = 1;
- enable();
- }
-
- void MTSignal(unsigned *semaphore)
- {
- disable();
- taskList[currentTaskID].semaphore = NULL;
- *semaphore = 0;
- WakeUpTasks(semaphore);
- ChangeTask();
- enable();
- }
-
- static void WakeUpTasks(unsigned *semaphore)
- {
- int i;
-
- for(i=0; i<MAX_TASKS; i++)
- if(taskList[i].semaphore == semaphore) {
- taskList[i].semaphore = NULL;
- if(taskList[i].status == WAITING)
- taskList[i].status = READY;
- return;
- }
- }
-
-
-
-
- void MTPuts(char *s)
- {
- MTWait(&IOsemaphore);
- puts(s);
- MTSignal(&IOsemaphore);
- }
-
- void MTXYPuts(int x,int y,char *s)
- {
- MTWait(&IOsemaphore);
- gotoxy(x,y);
- cputs(s);
- MTSignal(&IOsemaphore);
- }
-
-
- char MTGetch(void)
- {
- char ch;
-
- MTWait(&IOsemaphore);
- if (kbhit()) ch = getch();
- else ch = 0;
- MTSignal(&IOsemaphore);
- return ch;
- }
-
- void MTPutch(char c)
- {
- MTWait(&IOsemaphore);
- putch(c);
- MTSignal(&IOsemaphore);
- }
-
-
- void MTXYPutch(int x, int y, char c)
- {
- MTWait(&IOsemaphore);
- gotoxy(x,y);
- putch(c);
- MTSignal(&IOsemaphore);
- }
-
-
-
-
-
-
-
-